function MVVM(options) {
  this.$options = options;
  // 将data数据复制给data和_data
  // 将来：我们叫_data就是原data数据
  var data = (this._data = this.$options.data);
  var me = this;

  // 1. 数据代理
  // 提取data中所有属性
  // 进行遍历，调用_proxy数据代理的方法对所有data数据上的属性进行一一处理
  Object.keys(data).forEach(function (key) {
    me._proxy(key);
  });

  // 2. 数据劫持
  observe(data, this);

  // 3. 模板解析
  this.$compile = new Compile(options.el || document.body, this);
}

MVVM.prototype = {
  $watch: function (key, cb, options) {
    new Watcher(this, key, cb);
  },
  // 数据代理的方法
  _proxy: function (key) {
    var me = this;
    // 通过Object.defineProperty方法将data上属性重新定义在this上，同时定义属性的get、set方法
    // 当读取this上的数据时，会调用get方法，读取的实际是原data数据的值
    // 当设置this上的数据时，会调用set方法，设置的实际是原data数据的值
    Object.defineProperty(me, key, {
      configurable: false,
      enumerable: true,
      get: function proxyGetter() {
        return me._data[key];
      },
      set: function proxySetter(newVal) {
        me._data[key] = newVal;
      },
    });
  },
};
